#ifndef HOUGH_SPECTRUM_H
#define HOUGH_SPECTRUM_H

#include "line.h"
#include <vector>

/** Class HoughSpectrum allows the computation of Hough Transform (HT) 
 * and Hough Spectrum (HS). 
 * Given HT(\theta,\rho) from a set of points P, the corresponding HS is 
 * defined as
 *
 *   HS(\theta) = \sum_{\rho} HT(\theta,\rho)^2
 *
 * The maxima of HS corresponds to the main directions along which the points 
 * P are aligned. 
 */
class HoughSpectrum
{
public:
  /** Creates a HoughSpectrum object. 
   * The Hough space evaluates Hessian line parameters with theta in 
   * [-M_PI_2,M_PI_2[ and rho in [-rhoMax,rhoMax] and with bin size
   * of thetaStep*rhoStep.
   */
  HoughSpectrum(double thetaStep,double rhoStep,double rhoMax);
  
  /** Computes Hough Tranform and Hough Spectrum on the given number of points.
   */
  void compute(const line::point_vector& pv);
  
  /** Returns the value of Hough Tranform accumulator bin for the given theta 
   * and rho. 
   * If (theta,rho) is out of bounds, it returns zero.
   */
  unsigned int houghValue(double theta,double rho) const;
  
  /** Returns the value of Hough Tranform accumulator bin for the indices
   * of the bin. 
   */
  unsigned int houghValue(unsigned int itheta,unsigned int irho) const;
  
  /** Returns the value of Hough Spectrum for the given theta.
   */
  unsigned int spectrumValue(double theta) const;
  
  /** Returns the value of Hough Spectrum for the given theta index.
   */
  unsigned int spectrumValue(unsigned int itheta) const;
  
  /** Returns the value of theta corresponding to the maximum of Hough Spectrum.
   */
  double spectrumMax() const;
  
  /** Returns the index of theta bin corresponding to the maximum of 
   * Hough Spectrum.
   */
  unsigned int spectrumMaxIdx() const;
  
  /** Returns the number of bins of theta.
   */
  unsigned int thetaBinNum() const;
  
  /** Returns the number of bins of rho.
   */
  unsigned int rhoBinNum() const;
   
  /** Converts from theta to the corresponding bin index.
   */
  unsigned int thetaToIdx(double theta) const;
  
  /** Converts from theta bin index to the corresponding angular value.
   */
  double idxToTheta(unsigned int itheta) const;
  
  /** Converts from rho to the corresponding bin index.
   */
  unsigned int rhoToIdx(double rho) const;
  
  /** Converts from rho bin index to the corresponding value.
   */
  double idxToRho(unsigned int irho) const;

private:
  double thetaStep_;
  double rhoStep_;
  unsigned int thetaNum_;
  unsigned int rhoNum_;
  std::vector<unsigned int> houghSpace_;
  std::vector<unsigned int> houghSpectrum_;
  unsigned int maxIdx_;
  
  unsigned int thetaRhoBinToIdx(unsigned int itheta,unsigned int irho) const;
  
  unsigned int thetaRhoToIdx(double theta,double rho) const;
};

#endif

